﻿#region Copyright - edgecase software

/*
Copyright 2009-2015 edgecase software - http://www.edgecasesoftware.com/opensource
 
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in 
compliance with the License. You may obtain a copy of the License at
 
     http://www.apache.org/licenses/LICENSE-2.0
 
Unless required by applicable law or agreed to in writing, software distributed under the License is 
distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

See the License for the specific language governing permissions and limitations under the License.
*/

#endregion

namespace Turing
{
    using System;

    [Serializable]
    public abstract class Instruction
    {
        protected Instruction()
        {
            Type type = GetType();
            string name = type.Name.Replace("Instruction", string.Empty);
            Name = (string.IsNullOrEmpty(name)) ? type.Name : name;

            TransitionLeft = SingletonInstruction<EmptyInstruction>.Default;
            TransitionRight = SingletonInstruction<EmptyInstruction>.Default;
        }

        /// <summary>
        /// Gets or sets the previous action for the current instruction.
        /// </summary>
        public Instruction TransitionLeft { get; set; }

        /// <summary>
        /// Gets or sets the next action for the current instruction.
        /// </summary>
        public Instruction TransitionRight { get; set; }


        /// <summary>
        /// Gets or sets the name for the current instruction.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Processing of the current instruction.
        /// </summary>
        /// <returns>Returns the next <see cref="Instruction"/> that needs to be processed.</returns>
        public abstract Instruction Process(ITuringMachine machine);

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }

            return obj.GetType() == typeof (Instruction) && Equals((Instruction) obj);
        }

        public bool Equals(Instruction other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }

            return ReferenceEquals(this, other) || Equals(other.Name, Name);
        }

        public override int GetHashCode()
        {
            return (Name != null ? Name.GetHashCode() : 0);
        }
    }
}